//
// Context.h
// Usage: Process run context env
// Create Date: 2009-03-19
// Author: MaJiuyue
//
#ifndef _CONTEXT_H_
#define _CONTEXT_H_

#include "type.h"
#include "const.h"
#include "../pageman/PageTable.h"
#include "../pageman/AddressSpace.h"

class Context
{
private:
	// Page table of this context
	PageTable m_PT;
	// User address space
	AddressSpace m_AddressSpace;
	// Local descriptor table of this context
	DESCRIPTOR ldts[LDT_SIZE];

public:
	Context();
	Context(const Context & target);
	~Context();

public:
	void SwitchContext();
	void PrepareCallGate(addr_t entry, int param_cnt);

public:
	PageTable * GetPageTable() { return &m_PT; }

	// map 2^order pages started at paddr to vaddr
	void * MapPages(addr_t vaddr, addr_t paddr, int order);
	void UnmapPages(addr_t vaddr, int order);

	// map one page at paddr to vaddr
	void * MapPage(addr_t vaddr, addr_t paddr)
	{ return MapPages(vaddr, paddr, 0); }
	void UnmapPages(addr_t vaddr)
	{ UnmapPages(vaddr, 0); }

	// get physical address of vaddr
	addr_t GetPhyAddress(addr_t vaddr) 
	{ return m_PT.GetPhyAddress(vaddr); }

	// Clear page table
	void ClearPageTable();


	// Extend heap size
	addr_t ExtendHeap(int incr)
	{ return m_AddressSpace.ExtendHeap(incr); }

	// Extend stack size
	void ExtendStack(int incr)
	{ m_AddressSpace.ExtendStack(incr); }

	// Check if `addr' contained in user address space
	bool ValidAddress(addr_t addr)
	{ return m_AddressSpace.IsContain(addr); }

	// Allocate user space
	addr_t AllocUser(size_t size)
	{ return m_AddressSpace.AllocUser(size); }
	
	// Dealloc user space
	void DeallocUser(addr_t vaddr, size_t size)
	{ m_AddressSpace.DeallocUser(vaddr, size); }
};

#endif

